#coding=utf-8

import poplib
import email
import cStringIO
import base64
import re
import datetime
import wx
import os
from ConfigParser import ConfigParser 
import rarfile
import thread
import sys
reload(sys)
sys.setdefaultencoding('gbk')



class Mail_Tool(wx.Frame): 
    
    def __init__(self):  
        wx.Frame.__init__(self,   
                          parent=None,   
                          id=-1,   
                          title="mail_tool",   
                          pos=wx.DefaultPosition,  
                          size=(600,400),  
                          #style=wx.DEFAULT_FRAME_STYLE^(wx.RESIZE_BORDER |wx.MAXIMIZE_BOX),  
                          name="mainFrame"  
                          ) 
        #app=wx.App()
        #win=wx.Frame(None,title='scada tool',size=(700,500))
        

        bkg=wx.Panel(self)
        self.config = ConfigParser()   
        
        #邮箱信息输入
        #font = wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.BOLD) 
        self.mail_addr_text = wx.StaticText(bkg,label="邮箱".decode('utf-8', 'ignore'), style = wx.ALIGN_LEFT)
        #self.mail_addr_text.SetFont(font)
        self.mail_addr = wx.TextCtrl(bkg)
        
        self.mail_pwd_text = wx.StaticText(bkg,label="密码".decode('utf-8', 'ignore'), style = wx.ALIGN_LEFT)
        #self.mail_pwd_text.SetFont(font)
        self.mail_pwd = wx.TextCtrl(bkg,style = wx.TE_PASSWORD)
        
        
        #解压目录
        self.output_dir = wx.TextCtrl(bkg,style = wx.TE_READONLY)
        
        #密码字典设置
        self.pwd_text = wx.StaticText(bkg,label="解压密码".decode('utf-8', 'ignore'))
        self.pwd_input = wx.TextCtrl(bkg,style=wx.TE_MULTILINE | wx.HSCROLL |wx.VSCROLL)
        
        #进度条
        self.unrar_gauge = wx.Gauge(bkg,-1,100)  
        self.unrar_gauge.SetBezelFace(3)  
        self.unrar_gauge.SetShadowWidth(3)  
        #self.Bind(wx.EVT_IDLE, self.OnIdle) 
        
        
        self.output = wx.TextCtrl(bkg,style=wx.TE_MULTILINE | wx.HSCROLL |wx.VSCROLL | wx.TE_READONLY)
        #运行按钮
        self.run_btn=wx.Button(bkg,label='解压附件'.decode('utf-8', 'ignore'))
        
        self.save_btn=wx.Button(bkg,label='保存配置'.decode('utf-8', 'ignore'))
        
        self.mail_login_btn = wx.Button(bkg,label='下载附件'.decode('utf-8', 'ignore'))
        self.output_dir_btn = wx.Button(bkg,label='附件保存目录'.decode('utf-8', 'ignore'))
        
        self.run_btn.Bind(wx.EVT_BUTTON,self.Unrar_Thread)
        self.save_btn.Bind(wx.EVT_BUTTON,self.SaveConfig)
        self.mail_login_btn.Bind(wx.EVT_BUTTON,self.Get_Mail_Thread)
        self.output_dir_btn.Bind(wx.EVT_BUTTON,self.OnOutPath)
        
        self.hbox_input = wx.BoxSizer()
        self.hbox_input.Add(self.mail_addr_text,proportion=1,flag=wx.ALIGN_CENTER_VERTICAL,border=5)
        self.hbox_input.Add(self.mail_addr,proportion=4,flag=wx.EXPAND,border=5)
        self.hbox_input.Add(self.mail_pwd_text,proportion=1,flag=wx.ALIGN_CENTER_VERTICAL,border=5)        
        self.hbox_input.Add(self.mail_pwd,proportion=4,flag=wx.EXPAND,border=5)
        
        self.hbox_output = wx.BoxSizer()
        self.hbox_output.Add(self.output_dir,proportion=1,flag=wx.EXPAND,border=5)
    
        self.vbox1=wx.BoxSizer(wx.VERTICAL)
        self.vbox1.Add(self.hbox_input,proportion=1,flag=wx.EXPAND,border=5)
        self.vbox1.Add(self.hbox_output,proportion=1,flag=wx.EXPAND,border=5)
        
        self.vbox3=wx.BoxSizer(wx.VERTICAL)
        self.vbox3.Add(self.mail_login_btn,proportion=1,flag=wx.EXPAND,border=5)
        self.vbox3.Add(self.output_dir_btn,proportion=1,flag=wx.EXPAND,border=5)
        
        
        self.vbox2=wx.BoxSizer(wx.VERTICAL)
        self.vbox2.Add(self.run_btn,proportion=1,border=5)
        self.vbox2.Add(self.save_btn,proportion=1,border=5)
        
        self.hbox = wx.BoxSizer()
        self.hbox.Add(self.vbox1,proportion=1,flag=wx.EXPAND,border=5)
        self.hbox.Add(self.vbox3,proportion=0,flag=wx.LEFT,border=5)
        self.hbox.Add(self.vbox2,proportion=0,flag=wx.LEFT,border=5)
        
        
        
        self.hbox1 = wx.BoxSizer()
        self.hbox1.Add(self.pwd_text,proportion=1,flag=wx.EXPAND)
        self.hbox1.Add(self.unrar_gauge,proportion=1,flag=wx.EXPAND)
        
        self.hbox2 = wx.BoxSizer()
        self.hbox2.Add(self.pwd_input,proportion=1,flag=wx.EXPAND)
        self.hbox2.Add(self.output,proportion=1,flag=wx.EXPAND)
        

    
        self.vbox=wx.BoxSizer(wx.VERTICAL)
        self.vbox.Add(self.hbox,proportion=0,flag=wx.EXPAND|wx.ALL,border=5)
        self.vbox.Add(self.hbox1,proportion=0,flag=wx.EXPAND|wx.ALL,border=5)
        self.vbox.Add(self.hbox2,proportion=1,flag=wx.EXPAND|wx.ALL,border=5)
        
        self.ReadConfig()
        
        bkg.SetSizer(self.vbox)
        

        #mailhost = ''
        self.pp = poplib.POP3_SSL.__init__
        
    #邮箱登陆
    def MailLogin(self,event):
        self.output.WriteText("邮箱登录中......\n".decode('utf-8', 'ignore'))
        account = self.mail_addr.GetValue()
        password = self.mail_pwd.GetValue()

        if(account.endswith('@sgepri.sgcc.com.cn') == False):
            account += '@sgepri.sgcc.com.cn'
        #print account,password

        mail_host = 'mail.sgcc.com.cn'
        
        self.pp = poplib.POP3_SSL(mail_host)
        try:
            self.pp.user(account)
            self.pp.pass_(password)
            self.output.WriteText("登录成功...\n".decode('utf-8', 'ignore'))
            return True
        except:
            self.output.WriteText("登录失败...\n".decode('utf-8', 'ignore'))
            return False
        
    #读取更新时间
    def GetMailTime(self):
        path=sys.argv[0][0:sys.argv[0].rfind('\\')+1]
        os.chdir(path)
        
        date_format = '%Y-%m-%d %H:%M:%S'
        #try:
        time_str=''
        self.config.read('mail_tool.ini')   
        time_str = self.config.get('dir','last_get_time')
        print '+++++'+time_str
        return datetime.datetime.strptime(time_str,date_format)
        #except:
        #    return datetime.datetime.strptime('2000-1-1 00:00:00',date_format)
        
    #保存更新时间
    def SaveMailTime(self,time_str):
        path=sys.argv[0][0:sys.argv[0].rfind('\\')+1]
        os.chdir(path)
        
        try:
            print 'Save Time!!!!'+time_str
            self.config.read('mail_tool.ini')   
            self.config.set('dir','last_get_time',time_str)
            self.config.write(open("mail_tool.ini","w"))
            return True
        except:
            return False
            
    
    #配置读取，密码、路径、用户名
    def ReadConfig(self):
        try:
            self.config.read('mail_tool.ini')
            output_d = self.config.get('dir','output_dir')
            user = self.config.get('dir','user')
            self.output_dir.WriteText(output_d)
            self.mail_addr.WriteText(user)
        except:
            self.output.WriteText("路径配置读取失败!\n".decode('utf-8', 'ignore'))
        
        try:
            pwd_f = open('pwd.ini','r')
            for line in pwd_f.readlines():
                self.pwd_input.WriteText(line)
            pwd_f.close()
        except:
            self.output.WriteText("密码配置读取失败!\n".decode('utf-8', 'ignore'))
        
    #配置保存
    def SaveConfig(self,event):
        path=sys.argv[0][0:sys.argv[0].rfind('\\')+1]
        os.chdir(path)
        
        #保存目录配置
        save_success_flag  = True
        try:
            self.config.read('mail_tool.ini')   
            
            output_d = self.output_dir.GetValue()
            user = self.mail_addr.GetValue()

            self.config.set('dir','output_dir',output_d)
            self.config.set('dir','user',user)
            self.config.write(open("mail_tool.ini","w"))
        except:
            self.output.WriteText("路径配置保存失败!\n".decode('utf-8', 'ignore'))
            save_success_flag = False
        
        #保存密码配置
        pwd_text=self.pwd_input.GetValue()
        try:
            pwd_f = open('pwd.ini','w')
            pwd_f.truncate()
            pwd_f.write(pwd_text)
            pwd_f.close()
            
        except:
            self.output.WriteText("密码配置保存失败!\n".decode('utf-8', 'ignore'))
            save_success_flag = False
        
        if(save_success_flag == True):
            self.output.WriteText("配置保存成功!\n".decode('utf-8', 'ignore'))
        
    
    def showDirDialog(self,dialogTitle):  
         
         path = ""  
         dlg = wx.DirDialog(self, dialogTitle,  
                       style=wx.DD_DEFAULT_STYLE  
                        | wx.DD_DIR_MUST_EXIST  
                        | wx.DD_CHANGE_DIR  
                        )
         dlg.SetPath(self.output_dir.GetValue())
         if dlg.ShowModal() == wx.ID_OK:  
             path = dlg.GetPath()  
             #path = path.replace("\\","/")  
         dlg.Destroy()  
         return path  
    
    #文件夹选择框
    def OnOutPath(self,event):  
        path = self.showDirDialog("选择文件夹".decode('utf-8', 'ignore'))
        if path:  
            self.output_dir.Clear()  
            self.output_dir.WriteText(path)
            
    #下载邮件中的附件
    def Get_Mail_Thread(self,event):
        thread.start_new_thread(self.getMail,())
    
    def Unrar_Thread(self,event):
        thread.start_new_thread(self.Run,())
    
    def getMail(self):
        self.mail_login_btn.Disable()
        if self.MailLogin(self) == False:
            self.mail_login_btn.Enable()
            return
        self.output.WriteText('开始下载邮件...\n'.decode('utf-8','ignore'))
        diskroot = self.output_dir.GetValue()
        date_format = '%a, %d %b %Y %H:%M:%S'
        
        ret,size = self.pp.stat()
        mail_count = 0
        for i in range(ret):
            #从最近的邮件开始
            m = self.pp.retr(ret - i)
        
            buf = cStringIO.StringIO()
            for j in m[1]:
                print >>buf, j
            buf.seek(0)
            #解析信件内容
            msg = email.message_from_file(buf)
            #取信件头里的subject
            subject = msg.get("subject") 
            data_str = msg.get('date')
            #从时间字符串获取datetime
            mail_date = datetime.datetime.strptime(data_str[:-6],date_format)
            print mail_date
            #只获取3天内的邮件
            now_date = datetime.datetime.now()
            delta = now_date - mail_date
            if(delta.days > 3):
                break
            
            #创建日期文件夹
            dir_str = "%d_%d_%d"%(mail_date.year,mail_date.month,mail_date.day)
            last_save_datetime = self.GetMailTime()
            #邮件已下载过
            print mail_date,last_save_datetime
            if(mail_date <  last_save_datetime):
                break
            #保存最新的邮件时间
            if i == 0:
                newest_mail_time = mail_date
           
            os.chdir(diskroot)
            try:            
                os.mkdir(dir_str)
                os.chdir(dir_str)
            except:
                os.chdir(dir_str)
            #解码=?gbk?Q?=CF=E0=C6=AC?=这样的subject
            h = email.Header.Header(subject)
            dh = email.Header.decode_header(h)
            subcode = dh[0][1]
            subject = dh[0][0]
            if not subcode :
                subcode = 'utf-8'
            print "subcode",subcode
            print "subject:", unicode(subject,subcode)
            #if subject == sub:
            if True:              
                # 判断主题中是否包含 sub 关键字。
                # 循环信件中的每一个mime的数据块
                for par in msg.walk():
                    #这里要判断是否是multipart，是的话，里面的数据是无用的
                    if not par.is_multipart(): 
                        #如果是附件，取出附件的文件名
                        name = par.get_param("name") 
                        if name:
                        #有附件
                        #解码=?gbk?Q?=CF=E0=C6=AC.rar?=这样的文件名
                            h = email.Header.Header(name)
                            dh = email.Header.decode_header(h)
                            fname = dh[0][0]
                            fcode = dh[0][1]
                            if not fcode:
                                fcode = 'utf-8'
                            fname = unicode(fname,fcode)
                            print '附件名:',fname+' fcode:',fcode
                            #解码出附件数据，然后存储到文件中
                            data = par.get_payload(decode=True) 
                            
                            #图片不下载
                            if(fname.endswith('jpg') or fname.endswith('gif')):
                                continue
                            
                            #文件已下载过
                            if os.path.exists(fname) or os.path.exists('done_'+fname):
                                #self.output.WriteText((fname + '已存在，跳过..\n').encode('gbk'))
                                continue
                            try:
                                f = open(fname, 'wb')
                            except:
                                print '附件名有非法字符，自动换一个'
                                f = open('aaaa', 'wb')
                            f.write(data)
                            f.close()
                            mail_count += 1
                        else:
                            #不是附件，是文本内容
                            body = par.get_payload(decode=True) # 解码出文本内容，直接输出来就可以了。
                            #print 'body:'
                            #print 'body:',body       #中文没有处理好，所有没有输出了。
                        #print '+'*60 # 用来区别各个部分的输出
    
            #print '\n'
        
        self.mail_login_btn.Enable()
        self.SaveMailTime("%d-%d-%d %d:%d:%d"%(newest_mail_time.year,newest_mail_time.month,newest_mail_time.day,newest_mail_time.hour,newest_mail_time.minute,newest_mail_time.second))
        self.pp.quit()
        self.output.WriteText(('下载邮件完成,获取附件个数:%s\n\n'%mail_count).decode('utf-8','ignore'))
        return mail_count
    
    #解压函数
    def Run(self):
        self.run_btn.Disable()
        #获取密码字典
        pwd_text=self.pwd_input.GetValue()
        pwd_set = pwd_text.split('\n')
        
        output_d = self.output_dir.GetValue().decode('utf-8', 'ignore')
        
        #切换工作目录，防止unrar调用不了
        path=sys.argv[0][0:sys.argv[0].rfind('\\')+1]
        os.chdir(path)
        
        file_list=[]
        file_name_list=[]
        dir_list = []
        file_rename_list = []
        for root,dirs,files in os.walk(output_d):
            for file in files:
                
                file_dir = os.path.join(root,file)
                #用于解压后重命名rar文件，做标记
                rename_file_dir = os.path.join(root,('done_'+file))
                #绝对路径
                dir_list.append(root)
                file_list.append(file_dir)
                #用于显示
                file_name_list.append(file)
                file_rename_list.append(rename_file_dir)

        #进度条
        self.unrar_gauge.SetRange(len(file_list))
        for i in range(len(file_list)):
            #self.output.WriteText(file)
            file = file_list[i]
            file_name = file_name_list[i]
            
            self.unrar_gauge.SetValue(i+1)  
            
            #done开头的不需要解压
            if (file.endswith('.rar') == True) and (file_name.startswith('done') == False):
                self.output.WriteText(file_name+'\n')
                rf = rarfile.RarFile(file)
                #先尝试无密码解压
                try:
                    rf.setpassword(None)
                    rf.extractall(dir_list[i])
                    self.output.WriteText('解压成功,无密码'.decode('utf-8', 'ignore')+'\n\n')
                    os.rename(file,file_rename_list[i])
                    continue
                except:
                    success_flag = False
                    for pwd in pwd_set:
                        #if pwd == '':
                        #    continue
                        
                        try:
                            rf.setpassword(pwd)
                            rf.extractall(dir_list[i])
                            success_flag = True
                            self.output.WriteText('解压成功,密码:'.decode('utf-8', 'ignore')+pwd+'\n\n')
                            os.rename(file,file_rename_list[i])
                            break
                        except:
                            continue
                            #self.output.WriteText('password error  '+pwd+'\n')

                    if success_flag == False:
                        self.output.WriteText('解压失败'.decode('utf-8', 'ignore')+'\n\n')
                
        self.run_btn.Enable()
        
class Mail_App(wx.App):  
    def OnInit(self):  
        self.mainFrame = Mail_Tool()  
        self.mainFrame.Show()  
        self.SetTopWindow(self.mainFrame)  
        return True  
  
if __name__ == "__main__":  
    mail_app = Mail_App()  
    mail_app.MainLoop()  
